const fs = require('fs')
const { priKeyPath, pubKeyPath } = require('../config')
const jwt = require('jsonwebtoken')
const forge = require('node-forge')

// 生产公钥，私钥
function generateKeys() {
  const keypair = forge.pki.rsa.generateKeyPair({ bits: 2048, e: 0x10001 })
  const publicKey = forge.pki.publicKeyToPem(keypair.publicKey)
  const privateKey = forge.pki.privateKeyToPem(keypair.privateKey)
  fs.writeFileSync(priKeyPath, privateKey)
  fs.writeFileSync(pubKeyPath, publicKey)
}

// 加密
function encrypt(plain) {
  let public_key = fs.readFileSync(pubKeyPath, 'utf8')
  const publicKeyObj = forge.pki.publicKeyFromPem(public_key)
  const encrypted = publicKeyObj.encrypt(plain, 'RSAES-PKCS1-V1_5')
  return forge.util.encode64(encrypted)
}

//解密
function decrypt(cipher) {
  let private_key = fs.readFileSync(priKeyPath, 'utf8') // 私钥路径
  const privateKeyObj = forge.pki.privateKeyFromPem(private_key)
  // 如果密文是Base64编码的字符串，需要先将其转换为Buffer对象
  const bufferCipher = forge.util.decode64(cipher)

  return privateKeyObj.decrypt(bufferCipher, 'RSAES-PKCS1-V1_5')
}

/**
 * 将给定的数字转换为两位数的字符串表示
 * 如果给定的数字是一位数，会在其前面添加一个 '0'
 * 如果给定的数字已经是两位数或更多，将其转换为字符串后直接返回
 *
 * @param {number} num - 要转换的数字
 * @returns {string} - 转换后的两位数字符串表示
 */
function toDouble(num) {
  // 将数字转换为字符串，并检查是否至少有一位数
  // 如果是两位数或更多，直接返回原始字符串
  // 如果是一位数，前面添加 '0' 后返回
  return (String(num)[1] && String(num)) || '0' + num
}

function formatDate(date = new Date(), format = 'yyyy-MM-dd hh:mm:ss') {
  let regMap = {
    y: date.getFullYear(),
    M: toDouble(date.getMonth() + 1),
    d: toDouble(date.getDate()),
    h: toDouble(date.getHours()),
    m: toDouble(date.getMinutes()),
    s: toDouble(date.getSeconds()),
  }

  //逻辑(正则替换 对应位置替换对应值) 数据(日期验证字符 对应值) 分离
  return Object.entries(regMap).reduce((acc, [reg, value]) => {
    return acc.replace(new RegExp(`${reg}+`, 'g'), value)
  }, format)
}

// 自定义分页方法
async function pagination({
  model,
  select = '',
  pageNumber = 1,
  pageSize = 10,
  sort = {},
  query = {},
  lean = false,
  populate = [],
}) {
  const options = {
    // 分页选项
    page: pageNumber,
    limit: pageSize,
    select: `-__v ${select}`, // 可选的字段参数
    sort, // 可选的排序参数
    lean, // 转为纯对象
    leanWithId: false, // 保留id字段
    populate,
  }
  const paginateResult = await model.paginate(query, options)

  return {
    list: paginateResult.docs,
    pagination: {
      total: paginateResult.totalDocs,
      totalPages: paginateResult.totalPages,
      pageNumber: paginateResult.page,
      pageSize: paginateResult.limit,
    },
  }
}

// 生成正则表达式 ['blacklist', 'user', 'admin'] => /^(blacklist|user|admin)$/
function generateRegexFromArray(arr) {
  // 将数组元素转换为使用管道符号分隔的字符串
  const regexParts = arr.map((item) => item.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'))
  // 拼接正则表达式的其他部分
  return {
    regex: `^(${regexParts.join('|')})$`,
    error: `roles只能输入以下字符: ${arr.join(', ')}中的一个`,
  }
}

function jwtVerify(token) {
  try {
    let public_key = fs.readFileSync(pubKeyPath, 'utf8')
    const res = jwt.verify(token, public_key)
    console.log('res:', res)
    return res
  } catch (error) {
    console.log(error)
    return false
  }
}

function filterAndTruncateContent(content) {
  // 移除HTML标签
  const noHtmlContent = content.replace(/<[^>]*>/g, '')
  // 移除Markdown图片标签
  const noMarkdownImgContent = noHtmlContent.replace(/!\[.*?\]\(.*?\)/g, '')
  // 移除Markdown链接标签
  const noMarkdownLinkContent = noMarkdownImgContent.replace(/\[([^\]]+)\]\(.*?\)/g, '$1')
  // 移除Markdown粗体和斜体标签
  const noMarkdownBoldItalicContent = noMarkdownLinkContent.replace(/(\*\*|__)(.*?)\1/g, '$2')
  // 移除Markdown标题标签
  const noMarkdownHeaderContent = noMarkdownBoldItalicContent.replace(/^(#{1,6})\s+(.*)/gm, '$2')
  // 移除Markdown无序列表
  const noMarkdownUnorderedListContent = noMarkdownHeaderContent.replace(/(\*|\-|\+)\s+/g, '')
  // 移除Markdown有序列表
  const noMarkdownOrderedListContent = noMarkdownUnorderedListContent.replace(/\d+\.\s+/g, '')
  // 移除Markdown代码块
  const noMarkdownCodeContent = noMarkdownOrderedListContent.replace(/`{3}\s*([\s\S]*?)\s*`{3}/g, '$1')
  // 移除Markdown内联代码
  const noMarkdownInlineCodeContent = noMarkdownCodeContent.replace(/`(.*?)`/g, '$1')
  // 移除Markdown引用
  const noMarkdownQuoteContent = noMarkdownInlineCodeContent.replace(/(^>.*?$)/gm, '$1')
  // 移除Markdown分隔线
  const noMarkdownHrContent = noMarkdownQuoteContent.replace(/---|---/g, '')
  // 移除Markdown表格
  const noMarkdownTableContent = noMarkdownHrContent.replace(/\|.*?\|/g, '')
  // 移除Markdown任务列表
  const noMarkdownTaskListContent = noMarkdownTableContent.replace(/- \[[x\s]\] /g, '')
  // 移除所有空白字符（空格、换行、制表符等）
  const noWhitespaceContent = noMarkdownTaskListContent.replace(/\s+/g, '')

  // 截断超过100个字符的文本
  return noWhitespaceContent.length > 100 ? noWhitespaceContent.substring(0, 100) + '...' : noWhitespaceContent
}

//判断网址是否合法
function isUrlValid(url) {
  // 定义正则表达式规则
  const pattern = /^(?:https?:\/\/)?(juejin\.cn|blog\.csdn\.net|mp\.weixin\.qq\.com)\/.*/i
  // 测试 URL 是否匹配规则
  return pattern.test(url)
}

module.exports = {
  generateKeys,
  encrypt,
  decrypt,
  formatDate,
  pagination,
  generateRegexFromArray,
  jwtVerify,
  filterAndTruncateContent,
  isUrlValid,
}
